﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Minestorm.Evolved.Assets
{
    public class CustomEffect : ICustomEffect
    {
        Effect ICustomEffect.InnerEffect { get; set; }

        private Effect InnerEffect { get { return ((ICustomEffect)this).InnerEffect; } }

        public void Dispose()
        {
            ((ICustomEffect)this).InnerEffect.Dispose();
        }

        public Matrix World { get { return GetMatrix("World"); } set { Set("World", value); } }
        public Matrix View { get { return GetMatrix("View"); } set { Set("View", value); } }
        public Matrix Projection { get { return GetMatrix("Projection"); } set { Set("Projection", value); } }
        public Matrix WorldInverseTranspose 
        { 
            get { return GetMatrix("WorldInverseTranspose"); }
            set { Set("WorldInverseTranspose", value); Set("WorldInverseTransposeSpecified", true); }
        }

        protected void SetTechnique(string technique)
        {
            InnerEffect.CurrentTechnique = InnerEffect.Techniques[technique];
        }

        public static implicit operator Effect(CustomEffect effect)
        {
            return ((ICustomEffect)effect).InnerEffect;
        }

        protected Matrix GetMatrix(string name)
        {
            return InnerEffect.Parameters[name].GetValueMatrix();
        }

        protected Texture2D GetTexture2D(string name)
        {
            return InnerEffect.Parameters[name].GetValueTexture2D();
        }

        protected Vector2 GetVector2(string name)
        {
            return InnerEffect.Parameters[name].GetValueVector2();
        }

        protected Vector3 GetVector3(string name)
        {
            return InnerEffect.Parameters[name].GetValueVector3();
        }

        protected Vector4 GetVector4(string name)
        {
            return InnerEffect.Parameters[name].GetValueVector4();
        }

        protected Quaternion GetQuanternion(string name)
        {
            return InnerEffect.Parameters[name].GetValueQuaternion();
        }

        protected bool GetBoolean(string name)
        {
            return InnerEffect.Parameters[name].GetValueBoolean();
        }

        protected int GetInt32(string name)
        {
            return InnerEffect.Parameters[name].GetValueInt32();
        }

        protected float GetSingle(string name)
        {
            return InnerEffect.Parameters[name].GetValueSingle();
        }

        protected Color GetColor(string name)
        {
            var v4 = GetVector4(name);

            return new Color(v4);
        }

        protected void Set(string name, bool value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, Matrix value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, Texture2D value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, Vector2 value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, Vector3 value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, Vector4 value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, Quaternion value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, int value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, Single value)
        {
            InnerEffect.Parameters[name].SetValue(value);
        }

        protected void Set(string name, Color value)
        {
            InnerEffect.Parameters[name].SetValue(value.ToVector4());
        }

        protected static T CastTo<T>(Effect effect, Effects effectName)
            where T : class, ICustomEffect, new()
        {
            if (!effect.Name.Equals(effectName.ToString(), StringComparison.InvariantCultureIgnoreCase))
                throw new Exception("Cannot cast effect '" + effect.Name + "' to '" + effectName + "'");

            var fx = new T();
            fx.InnerEffect = effect;
            return fx;
        }
    }
}
